package com.szw.dlyk.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.szw.dlyk.constant.Constant;
import com.szw.dlyk.domain.Permission;
import com.szw.dlyk.domain.Role;
import com.szw.dlyk.domain.User;
import com.szw.dlyk.dto.UserDtoLogin;
import com.szw.dlyk.manager.RedisManager;
import com.szw.dlyk.mapper.PermissionMapper;
import com.szw.dlyk.mapper.RoleMapper;
import com.szw.dlyk.query.BaseQuery;
import com.szw.dlyk.query.UserQuery;
import com.szw.dlyk.service.UserService;
import com.szw.dlyk.mapper.UserMapper;
import com.szw.dlyk.util.CacheUtil;
import jakarta.annotation.Resource;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* @author asus
* @description 针对表【t_user(用户表)】的数据库操作Service实现
* @createDate 2024-01-21 18:16:51
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private RedisManager redisManager;

    @Resource
    private PermissionMapper permissionMapper;

    /**
     * 登录查询
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getLoginAct,username);
        User user = userMapper.selectByLoginAct(username);

        if (user == null) {
            throw new UsernameNotFoundException("登录账号不存在");
        }
        UserDtoLogin userDtoLogin = BeanUtil.copyProperties(user, UserDtoLogin.class);

        //查询当前用户的角色
        List<Role> roleList = roleMapper.selectUserRoleById(userDtoLogin.getId());
        List<String> list = new ArrayList<>();
        roleList.forEach(role -> {
                list.add(role.getRole());
        });
        //设置用户的角色
        userDtoLogin.setRoleList(list);
        //查询一下该用户有哪些菜单
        List<Permission> menuPermissonList = permissionMapper.selectMenuPermissonListByUserId(userDtoLogin.getId());
        userDtoLogin.setMenuPermissionList(menuPermissonList);

        //查询一下该用户有哪些功能权限
        List<Permission> buttonPermissionList = permissionMapper.selectButtonPermissionByUserId(userDtoLogin.getId());
        List<String> stringPermissionList = new ArrayList<>();
        buttonPermissionList.forEach(permission -> {
            stringPermissionList.add(permission.getCode());//权限标识符
        });
        //设置用户的权限标识符
        userDtoLogin.setPermissionList(stringPermissionList);
        return userDtoLogin;
    }

    @Override
    public PageInfo<User> getUsersByPage(Integer current) {
        // 1.设置PageHelper
        PageHelper.startPage(current, Constant.PAGE_SIZE);
        // 2.查询
        List<User> list = userMapper.selectUserByPage(BaseQuery.builder().build());
        // 3.封装分页数据到PageInfo
        PageInfo<User> info = new PageInfo<>(list);

        return info;
    }

    @Override
    public User getUserDetailById(Integer id) {
        return userMapper.selectUserById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int saveUser(UserQuery userQuery) {
        //把UserQuery对象里面的属性数据复制到User对象里面去(复制要求：两个对象的属性名相同，属性类型要相同，这样才能复制)
        User user = BeanUtil.copyProperties(userQuery, User.class);
        user.setLoginPwd(passwordEncoder.encode(userQuery.getLoginPwd()));
        user.setCreateTime(new Date());

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDtoLogin user1 = (UserDtoLogin) authentication.getPrincipal();

        user.setCreateBy(user1.getId());
        return userMapper.saveUser(user);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateUser(UserQuery userQuery) {
        User user = BeanUtil.copyProperties(userQuery, User.class);
        if (!StrUtil.isBlank(userQuery.getLoginPwd())){
            user.setLoginPwd(passwordEncoder.encode(userQuery.getLoginPwd()));
        }
        user.setEditTime(new Date());

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDtoLogin user1 = (UserDtoLogin) authentication.getPrincipal();

        user.setEditBy(user1.getId());
        return userMapper.updateUser(user);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteUserById(Integer id) {
        return userMapper.deleteUserById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int batchDeleteUser(List<String> idList) {
        return userMapper.deleteUserByIds(idList);
    }

    @Override
    public List<User> getOwnerList() {
        //1.从redis中查询
        // 2.查不到 查数据库 并且把数据放到redis(3/5min)
        return CacheUtil.getCacheData(() -> {
                    //从redis查询数据
                    return (List<User>)redisManager.getValue(Constant.REDIS_OWNER_KEY);
                },
                ()->{
                    //生产，从mysql查询数据
                    return userMapper.selectByOwner();
                },
                (t)->{
                    //消费
                    redisManager.setValue(Constant.REDIS_OWNER_KEY,t);
                }
        );
    }

}




